﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using LiteBlog.IoC;
using System.Web.Mvc;
using LiteBlog.Models;
using LiteBlog.Common.Entities;
using Moq;
using LiteBlog.Components.Contracts;
using LiteBlog.Controllers.Contracts;
using System.ServiceModel.Syndication;
using LiteBlog.Controllers.Helpers;
using LiteBlog.Common.Enums;
using System.Collections.Generic;

namespace LiteBlog.Controllers.Tests
{
    [TestClass]
    public class HomeControllerTests : ControllerTests<IHomeController>
    {
        [TestMethod]
        public void IndexLoadsSettings()
        {
            _controller.Index(null);
            var mock = Mock.Get<ISettingsComp>(_controller.SettingsComponent);
            mock.Verify(se => se.Load());
        }

        [TestMethod]
        public void IndexGetsPublished()
        {
            var mock = Mock.Get<IBlogComp>(_controller.BlogComponent);
            _controller.Index(null);
            mock.Verify(s => s.GetPublished());
        }

        [TestMethod]
        public void IndexGetsPost()
        {
            var postInfos = new List<PostInfo>();
            postInfos.Add(new PostInfo { FileID = "Sample-Post" });
            var blogMock = Mock.Get<IBlogComp>(_controller.BlogComponent);
            blogMock.Setup(b => b.GetPublished())
                    .Returns(postInfos);
            var postMock = Mock.Get<IPostComp>(_controller.PostComponent);
            postMock.Setup(p => p.Load(It.IsAny<string>()))
                    .Returns(new Post());

            _controller.Index(null);

            postMock.Verify(p => p.Load("Sample-Post"));
        }

        [TestMethod]
        public void IndexIsValid()
        {
            var postInfos = new List<PostInfo>();
            postInfos.Add(new PostInfo { FileID = "Sample-Post" });
            var blogMock = Mock.Get<IBlogComp>(_controller.BlogComponent);
            blogMock.Setup(b => b.GetPublished())
                    .Returns(postInfos);
            var postMock = Mock.Get<IPostComp>(_controller.PostComponent);
            postMock.Setup(p => p.Load(It.IsAny<string>()))
                    .Returns(new Post { Title = "Sample Post" });

           var actionResult = _controller.Index(null);

           var model = GetModel(actionResult) as PostCollectionModel;
           Assert.AreEqual("Sample Post", model.PostCollection[0].Title);
        }

        [TestMethod]
        public void IndexDoesNotGetAuthorIfNotAuthenticated()
        {
            // This test should run before the  IndexGetsAuthorIfAuthenticated test
            _controller.UserModel = new UserModel(null, false);
            _controller.Index(null);
            var mock = Mock.Get<IAuthorComp>(_controller.AuthorComponent);
            mock.Verify(a => a.Get(It.IsAny<string>()), Times.Never());
        }

        [TestMethod]
        public void IndexGetsAuthorIfAuthenticated()
        {
            _controller.UserModel = new UserModel("Admin", true);
            _controller.Index(null);
            var mock = Mock.Get<IAuthorComp>(_controller.AuthorComponent);
            mock.Verify(a => a.Get(It.IsAny<string>()), Times.Once);
        }

        [TestMethod]
        public void TitleLoadsSettings()
        {
            _controller.Title();
            var mock = Mock.Get<ISettingsComp>(_controller.SettingsComponent);
            mock.Verify(se => se.Load());
        }

        [TestMethod]
        public void TitleGetsPages()
        {
            _controller.Title();
            var mock = Mock.Get<IPageComp>(_controller.PageComponent);
            mock.Verify(p => p.GetPagesInHeaderMenu());
        }
        
        [TestMethod]
        public void TitleIsValid()
        {
            _settings.Name = "LiteBlog";
            var actionResult = _controller.Title();
            var titleModel = GetModel(actionResult) as TitleModel;
            Assert.AreEqual("LiteBlog", titleModel.Title);
        }

        [TestMethod]
        public void WidgetIncrementsHits()
        {
            _controller.Widget();
            var mock = Mock.Get<IStatComp>(_controller.StatComponent);
            mock.Verify(s => s.IncrementHits());
        }

        [TestMethod]
        public void WidgetLoadsStatistics()
        {
            _controller.Widget();
            var mock = Mock.Get<IStatComp>(_controller.StatComponent);
            mock.Verify(s => s.Load());
        }

        [TestMethod]
        public void StatisticsIsValid()
        {
            _controller.Statistics();
            var mock = Mock.Get<IStatComp>(_controller.StatComponent);
            mock.Verify(s => s.Load());
        }

        [TestMethod]
        public void AtomIncrementsFeedCount()
        {
            _controller.Atom();
            var mock = Mock.Get<IStatComp>(_controller.StatComponent);
            mock.Verify(s => s.IncrementFeeds());
        }

        [TestMethod]
        public void AtomGetsFeed()
        {
            _controller.Atom();
            var mock = Mock.Get<IFeedComp>(_controller.FeedComponent);
            mock.Verify(f => f.GetFeed());
        }

        [TestMethod]
        public void FeedTypeIsAtom()
        {
            var actionResult = _controller.Atom() as FeedActionResult;
            Assert.AreEqual(FeedType.ATOM, actionResult.FeedType);
        }

        [TestMethod]
        public void RssIncrementsFeedCount()
        {
            _controller.Rss();
            var mock = Mock.Get<IStatComp>(_controller.StatComponent);
            mock.Verify(s => s.IncrementFeeds());
        }

        [TestMethod]
        public void RssGetsFeed()
        {
            _controller.Rss();
            var mock = Mock.Get<IFeedComp>(_controller.FeedComponent);
            mock.Verify(f => f.GetFeed());
        }

        [TestMethod]
        public void FeedTypeIsRss()
        {
            var actionResult = _controller.Rss() as FeedActionResult;
            Assert.AreEqual(FeedType.RSS, actionResult.FeedType);
        }
    }
}
